﻿using MahApps.Metro;
using SQX.DataModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Documents;
using System.Windows.Media;

namespace SQX.ViewModel
{
    public class MainWindowViewModel : ViewModelBasic
    {
        private ActiveThreadStatus threadStatus;
        private DateTime operationStart;
        private Timer queryTimer;
        private QueryViewModelBasic activeModel;
        private FontFamily editorFontFamily;
        private KeyValuePair<string,int> editorFontSize = new KeyValuePair<string,int>("",0);
        private int themeIndex = 0;
        private string activeThemeName;


        public MainWindowViewModel()
        {
            ModelCollection = new ObservableCollection<QueryViewModelBasic>();
            UIFonts = new ObservableCollection<FontFamily>();
            ThemeNames = new ObservableCollection<string>();
            themeIndex = Properties.Settings.Default.UserThemeIndex;
            var savedFont = Properties.Settings.Default.UserFont;
            var savedFontSize = Properties.Settings.Default.UserFontSize;

            // add themes
            foreach (Accent ac in ThemeManager.Accents)
            {
                ThemeNames.Add(ac.Name);
            }

            ActiveThemeName = ThemeNames[themeIndex];
            // add fonts
            foreach (FontFamily fm in Fonts.SystemFontFamilies)
            {
                if (fm.Source == savedFont) { this.EditorFontFamily = fm; }
                UIFonts.Add(fm);
            }

            FontSizes = new ObservableCollection<KeyValuePair<string, int>>();
            // standard fontsize pack for editors
            for (int i = 8; i < 24;++i)
            {
                var kvp = new KeyValuePair<string,int>(i.ToString() + " pt", i);
                FontSizes.Add(kvp);
                if (i == savedFontSize) EditorFontSize = kvp;
            }


        }

        public enum ActiveThreadStatus
        {
            [Description("Idle")]Idle = 0,
            [Description("Running query")]Running = 1,
            [Description("Parsing dataset")]Parsing = 2,
            [Description("Cancelling query")]Cancelling = 3
        }

        private void InvokeTimePassed(Object stateInfo)
        {
            OnPropertyChanged("TimePassed");
        }

        public void RunQueryTimer()
        {
            operationStart = DateTime.Now;
            TimerCallback tcb = this.InvokeTimePassed;
            queryTimer = new Timer(tcb, null, 0, 100);
        }

        public void StopQueryTimer()
        {
            queryTimer.Dispose();
        }

        public string TimePassed
        {
            get
            {
                if (this.IsThreadActive)
                {
                    return DateTime.Now.Subtract(operationStart).ToString("hh\\:mm\\:ss");
                }
                else return "00:00:00";
            }
        }

        public ActiveThreadStatus ThreadStatus
        {
            get { return threadStatus; }
            set { threadStatus = value; OnPropertyChanged("IsThreadActive"); OnPropertyChanged("ThreadStatusText"); } // change madness to converter please
        }

        public bool IsThreadActive
        {
            get
            {
                return ((int)ThreadStatus == 1 | (int)ThreadStatus == 2);
            }
        }

        public string ThreadStatusText
        {
            get
            {
                return Service.GetDescription(ThreadStatus);
            }
        }

        public QueryViewModelBasic ActiveModel
        {
            get { return activeModel; }
            set { activeModel = value; OnPropertyChanged("ActiveModel"); }
        }

        public ObservableCollection<QueryViewModelBasic> ModelCollection { get; set; }

        public ObservableCollection<FontFamily> UIFonts { get; set; }

        public KeyValuePair<string, int> EditorFontSize
        {
            get { return editorFontSize; }
            set 
            { 
                editorFontSize = value; 
                OnPropertyChanged("EditorFontSize");
                Properties.Settings.Default.UserFontSize = (short)editorFontSize.Value;
                Properties.Settings.Default.Save();
            }
        }

        public ObservableCollection<KeyValuePair<string, int>> FontSizes { get; set; }

        public FontFamily EditorFontFamily 
        { 
            get { return editorFontFamily; }
            set 
            { 
                editorFontFamily = value; OnPropertyChanged("EditorFontFamily"); 
                Properties.Settings.Default.UserFont = editorFontFamily.Source;
                Properties.Settings.Default.Save();
            }
        }

        public void SaveActiveQuery()
        {
            // first check if query was saved already
            var path = this.ActiveModel.ActiveQuery.Header;
            if (!File.Exists(path))
            {

                System.Windows.Forms.SaveFileDialog sdlg = new System.Windows.Forms.SaveFileDialog();
                sdlg.Filter = "SQX Query File|" + this.ActiveModel.ActiveQuery.SaveFileExtension;
                sdlg.Title = "Save query...";
                sdlg.ShowDialog();
                string target = sdlg.FileName;
                if (sdlg.CheckPathExists && target != "")
                {
                    using (StreamWriter sw = File.CreateText(target))
                    {
                        sw.WriteAsync(this.ActiveModel.ActiveQuery.Text);
                    }

                    this.ActiveModel.ActiveQuery.Header = sdlg.FileName;
                }
            } // end if not saved previously
            else
            {
                using (StreamWriter sw = File.CreateText(path))
                {
                    sw.WriteAsync(this.ActiveModel.ActiveQuery.Text);
                }
            } // if it was - overwrite file
            this.ActiveModel.ActiveQuery.IsSaved = true;
        }

        public TextPointer CurrentPosition { get; set; }

        public QueryViewModelBasic FindModel(string ModelTypeName)
        {
            var found = this.ModelCollection.ToList().Find(model =>
                {
                    return model.GetType().Name == ModelTypeName;
                });
            return found;
        }

        public TextRange CurrentRange { get; set; }
        public string InputSymbol { get; set; }

        public string ActiveThemeName 
        { 
            get { return activeThemeName; }
            set 
            { 
                activeThemeName = value; 
                OnPropertyChanged("ActiveThemeName");
                ThemeManager.ChangeAppStyle(App.Current,
                    ThemeManager.GetAccent(activeThemeName),
                    ThemeManager.GetAppTheme("BaseLight"));
            }
        }

        public ObservableCollection<string> ThemeNames { get; set; }

        public void NextAccent()
        {
            if (themeIndex < ThemeNames.Count - 1)
            {
                themeIndex += 1;
            }
            else
            {
                themeIndex = 0;
            }
            Properties.Settings.Default.UserThemeIndex = (short)themeIndex;
            Properties.Settings.Default.Save();

            ActiveThemeName = ThemeNames[themeIndex];
        }
    }
}
